Skip to content

Improve performance by caching src/dest when applying resource manifests#1235

Merged
openshift-merge-robot merged 1 commit intoopenshift:masterfrom
jerpeter1:avoid-deep-copy
Dec 14, 2021
Merged

Improve performance by caching src/dest when applying resource manifests#1235
openshift-merge-robot merged 1 commit intoopenshift:masterfrom
jerpeter1:avoid-deep-copy

Conversation

@jerpeter1
Copy link
Copy Markdown
Member

If we see that neither the manifest being applied (by caching a hash of the manifest),
or the existing resource in the cluster (by caching the resourceVersion) has
changed since the manifest was last updated, applying the resource can be
skipped, since it won't actually do anything.

@jerpeter1
Copy link
Copy Markdown
Member Author

/hold

@openshift-ci openshift-ci Bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. and removed do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels Oct 25, 2021
@jerpeter1
Copy link
Copy Markdown
Member Author

/unhold

@jerpeter1
Copy link
Copy Markdown
Member Author

@deads2k - can you please take a look at this PR?

@jerpeter1
Copy link
Copy Markdown
Member Author

/assign deads2k

}

// map of name,kind to resourceHash (of last applied resource) : resourceVersion(when resource was applied)
var cachedResourceVersions map[CachedVersionKey]CachedResource = make(map[CachedVersionKey]CachedResource)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no global state please. I'd rather either

  1. break everyone and change the methods
  2. create new methods that accept a cache or use a method receiver struct to track it and have the staticresource controller maintain them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose option 2. Since there are so many users of resourceapply.ApplyFoo functions, I decided to create new functions that accept a cache and use those new functions from static resource controller, buta t some point I'd like to go back and add something that lets everyone take advantage of the enhanced performance.

}

type CachedResource struct {
resourceHash, resourceVersion string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for future readers can you godoc these. I think that resourcehash is the hash of the required in an ApplyFoo that is computed in case the input changes and resourceVersion is the received resourceVersion from the apiserver in response to an update that is comparable to the GET.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// map of name,kind to resourceHash (of last applied resource) : resourceVersion(when resource was applied)
var cachedResourceVersions map[CachedVersionKey]CachedResource = make(map[CachedVersionKey]CachedResource)

func updateCachedResourceVersion(name string, kind string, namespace string, resourceHash string, resourceVersion string) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this took a runtime.Object instead of a resourceVersion, you'd be able to simply call updateCachedResourceVersion and have it clear on nil (or do nothing) and avoid all the nil checks in callers.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// if the manifest applied is the same as the last time this resource was
// updated, and the resourceVersion also hasn't changed, we don't need to
// actually do anything
func checkCachedResourceVersion(name string, kind string, namespace string, resourceHash string, resourceVersion string) bool {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasResourceMutated or resourceChanged or mayNeedUpdate?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with safeToSkipApply

Comment thread pkg/operator/resource/resourceapply/core.go
// ApplyNamespace merges objectmeta, does not worry about anything else
func ApplyNamespace(ctx context.Context, client coreclientv1.NamespacesGetter, recorder events.Recorder, required *corev1.Namespace) (*corev1.Namespace, bool, error) {
existing, err := client.Namespaces().Get(ctx, required.Name, metav1.GetOptions{})
resourceHash := hashOfResourceStruct(required)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While technically more efficient, this requires callers to compute instead of simply passing their required to checkCachedResourceVersion and updateCachedResourceVersion. My preference is to pass the runtime.Objects around and know that if we actually issued an update, it was significantly more expensive than re-computing the hash.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. It is less performant than the previous implementation (since we're calculating the hash of required several times from the same ApplyFoo, but it's still an improvement from the prior implementation.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 10, 2021
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Dec 10, 2021

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jerpeter1
To complete the pull request process, please ask for approval from deads2k after the PR has been reviewed.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 10, 2021
@jerpeter1
Copy link
Copy Markdown
Member Author

/retest-required

…when applying resource manifests, and skipping updating the apiserver when it won't do anything
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Dec 14, 2021

@jerpeter1: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants